home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / dviware / dviapollo / dvisuntool.c- < prev    next >
Text File  |  1990-10-01  |  26KB  |  819 lines

  1.  /* @(#)dvisuntool.c    1.17 2/19/87 */
  2. #include "header.h"
  3. #include "genwindow.h"
  4. #define NEW(A) ((A *) malloc(sizeof(A)))
  5. /* #define DEBUG   1*/            /* for massive printing of input */
  6.                     /* trace information; select by -d */
  7.                     /* option before filename. */
  8. #ifdef DEBUG
  9. int Debug = 0;
  10. #endif
  11.  
  12. #define USEGLOBALMAG 1            /* when defined, the dvi global
  13.                           magnification is applied */
  14.  
  15. #define  FIRSTPXLCHAR      0
  16. #define  LASTPXLCHAR     127
  17. #define  NPXLCHARS       128
  18. #define  PXLID          1001
  19. #define  READ              4   /* for access() */
  20. #define  hconvRESOLUTION RESOLUTION /* These numbers are right for my */
  21. #define  vconvRESOLUTION RESOLUTION /* particular sun3 display.  TSF */
  22. #define BORDER_BLACK 3 /* Width of border, in pixels.*/
  23. #define PAGE_HEIGHT 11 /* Height of page, in inches. */
  24. #define PAGE_WIDTH 8.5 /* Width of page, in inches. */
  25. #define  STACKSIZE       100   /* This is bogus.  The DVI file gives */
  26.                    /* us a stacksize, we should use it.*/
  27.  
  28. #define  MAXOPEN 10     /* _NFILES     limit on number of open PXL files */
  29.  
  30. float    ActualFactor();
  31. FILE*    fopen();
  32. void    draw_borders();
  33. void    fatal();
  34. void    FindPostAmblePtr();
  35. void    GetBytes();
  36. void    getfontdef();
  37. void    MoveDown();
  38. void    MoveOver();
  39. void    OpenFontFile();
  40. int    PixRound();
  41. int    ReadFontDef();
  42. int    readpostamble();
  43. void    SetChar();
  44. void    SetFntNum();
  45. void    SetRule();
  46. void    SkipFontDef();
  47. CharImage read_char();
  48. void show_char();
  49. struct char_entry {        /* character entry */
  50.    unsigned short width, height;/* width and height in pixels */
  51.    short xOffset, yOffset;      /* x offset and y offset in pixels */
  52.    struct {
  53.        int isloaded;
  54.        union {
  55.      int fileOffset;
  56.      CharImage pixrectptr; /* Not a pixrect if we're
  57.                   using X! */
  58.        } address;
  59.    } where;
  60.    int tfmw;            /* TFM width */
  61. };
  62.  
  63. struct font_entry {  /* font entry */
  64.    int k, c, s, d, a, l;
  65.    char n[STRSIZE];    /* FNT_DEF command parameters */
  66.    int font_space;    /* computed from FNT_DEF s parameter */
  67.    int font_mag;    /* computed from FNT_DEF s and d parameters */
  68.    char name[STRSIZE];    /* full name of PXL file */
  69.    FILE *font_file_id;  /* file identifier (0 if none) */
  70.    int magnification;    /* magnification read from PXL file */
  71.    int designsize;    /* design size read from PXL file */
  72.    struct char_entry ch[NPXLCHARS];/* character information */
  73.    struct font_entry *next;
  74. };
  75.  
  76. struct pixel_list
  77. {
  78.     FILE *pixel_file_id;        /* file identifier */
  79.     int use_count;              /* count of "opens" */
  80.     struct font_entry *fptr     /* ptr to its font entry */
  81. };
  82.  
  83. int hconv; /*  DVI units per pixel */
  84. int vconv;
  85. int den;            /* denominator specified in preamble */
  86. struct font_entry *fontptr;     /* font_entry pointer for current font */
  87. struct font_entry *hfontptr=NULL;/* font_entry pointer for all fonts */
  88. struct font_entry *closedfonts=NULL; /* font_entry pointer for list of */
  89.                      /* closed fonts.  Hfontptr gets */
  90.                      /* put here when a file is */
  91.                      /* closed. */
  92. int h;                /* current horizontal position */
  93. int v;                /* current vertical position */
  94. int mag;            /* magnification specified in preamble */
  95. int nopen = 0;            /* number of open PXL files */
  96. int num;            /* numerator specified in preamble */
  97. struct font_entry *pfontptr = NULL; /* most recent font_entry pointer returned from OpenFontFile. */
  98. struct pixel_list pixel_files[MAXOPEN+1];
  99.                                 /* list of open PXL file identifiers */
  100.  
  101. long postambleptr;        /* Pointer to the postamble */
  102. FILE *pxlfp;            /* PXL file pointer */
  103.  
  104. /* This is called when a DVI file is closed.  It resets *hfontptr to */
  105.  /* NULL, and sets closedfonts to the old linked list stored in */
  106.  /* closedfonts appended with the value of hfontptr. */
  107. void close_fonts ()
  108. {
  109.   if (closedfonts == NULL) {
  110.     closedfonts = hfontptr;
  111.   } else {
  112.     struct font_entry *scanner;
  113.     for (scanner = closedfonts; scanner -> next != NULL; scanner =
  114.      scanner -> next);
  115.     scanner -> next = hfontptr;
  116.   };
  117.   hfontptr = NULL;
  118. }
  119.  
  120. int Nosignextend(fp, n)    /* return n byte quantity from file fp */
  121.      register FILE *fp;    /* file pointer    */
  122.      register int n;        /* number of bytes */
  123. {
  124.   register int x;        /* number being constructed */
  125.  
  126.   x = 0;
  127.   while (n--)  {
  128.     x <<= 8;
  129.     x |= getc(fp);
  130.   }
  131.   return(x);
  132. }
  133.  
  134. int signextend(fp, n)   /* return n byte quantity from file fp */
  135.      register FILE *fp;  /* file pointer    */
  136.      register int n;     /* number of bytes */
  137. {
  138.   int n1;            /* number of bytes        */
  139.   register int x;        /* number being constructed */
  140.  
  141.   x = getc(fp);            /* get first (high-order) byte */
  142.   n1 = n--;
  143.   while (n--)  {
  144.     x <<= 8;
  145.     x |= getc(fp);
  146.   }
  147.   /* NOTE: This code assumes that the right-shift is an arithmetic, rather
  148.      than logical, shift which will propagate the sign bit right.   According
  149.      to Kernighan and Ritchie, this is compiler dependent! */
  150.   /* Also, assuming sizeof(int) == 4 is machine dependent (32-bit ints) */
  151.   x<<=32-8*n1;
  152.   x>>=32-8*n1;            /* sign extend */
  153. #ifdef DEBUG
  154.   if (Debug)
  155.     {
  156.       fprintf(stderr,"\tsignextend(fp,%d)=%X\n",n1,x);
  157.     }
  158. #endif
  159.   return(x);
  160. }
  161.  
  162. /* This reads the stuff between the front of the dvi file and the */
  163.  /* start of the first page.  It returns the number of pages in the */
  164.  /* document. */
  165. int start_reading_dvi_file(dvifp)
  166.      FILE *dvifp;
  167. {
  168.   int pages;
  169.   fseek (dvifp, (long) 0, 0);
  170.   if ((Nosignextend(dvifp, 1)) != PRE)  {
  171.     fatal("PRE doesn't occur first. Are you sure this is a DVI file?");
  172.   }
  173.   {
  174.     int i;
  175.     i = signextend(dvifp, 1);
  176.     if (i != DVIFORMAT)  {
  177.       fatal ("DVI format = %d, can only process DVI format %d files\n\n",
  178.          i, DVIFORMAT);
  179.     }
  180.   }
  181.   pages = readpostamble (dvifp);
  182.   if (preload) getfontdef (dvifp);
  183.   fseek(dvifp, (long) 14, 0);
  184.   {
  185.     char n[STRSIZE];
  186.     GetBytes(dvifp, n, Nosignextend(dvifp, 1));
  187.   };
  188.   return (pages);
  189. }
  190.  
  191. /* Draw borders around the page.  Knuth says that the (0,0) point in */
  192.  /* DVI units should be one inch from the top and from the left edges */
  193.  /* of the page.  The page is 8.5 by 11 inches, of course. The borders */
  194.  /* are BORDER_BLACK pixels wide, and it lies just barely outside of the page.*/
  195. void draw_borders(xscreen, yscreen)
  196.      int xscreen, yscreen;
  197. {
  198.   int height = PAGE_HEIGHT * RESOLUTION; /* These are in pixels. */
  199.   int width = PAGE_WIDTH * RESOLUTION;
  200.   int x = - RESOLUTION - xscreen;
  201.   int  y = - RESOLUTION - yscreen;
  202.  
  203.   /* top horizontal */
  204.   black_box (x - BORDER_BLACK, y - BORDER_BLACK, 
  205.          width + 2 * BORDER_BLACK, BORDER_BLACK);
  206.   /* bottom horizontal */
  207.   black_box (x - BORDER_BLACK, y + height,
  208.          width + 2 * BORDER_BLACK, BORDER_BLACK);
  209.   /* left vertical */
  210.   black_box (x - BORDER_BLACK, y - BORDER_BLACK,
  211.          BORDER_BLACK, height + 2 * BORDER_BLACK);
  212.   /* right vertical */
  213.   black_box (x + width, y - BORDER_BLACK, 
  214.          BORDER_BLACK,  height + 2 * BORDER_BLACK);
  215. }
  216.  
  217. void showpage (cpagep, ppagep, SkipMode, PagesLeft, borders, dvifp, xscreen, yscreen)
  218.      long *cpagep, *ppagep;
  219.      int SkipMode, PagesLeft;
  220.      BOOLEAN borders; /* Whether to draw borders.*/
  221.      FILE *dvifp;
  222.      int xscreen, yscreen;
  223. {
  224.   int w;            /* current horizontal spacing */
  225.   int x;            /* current horizontal spacing */
  226.   int y;            /* current vertical spacing */
  227.   int z;            /* current vertical spacing */
  228.   int sp;            /* stack pointer */
  229.   struct stack_entry {        /* stack entry */
  230.     int h, v, w, x, y, z;    /* what's on stack */
  231.   };
  232.   struct stack_entry stack[STACKSIZE]; /* stack */
  233.   int SkipEOP = FALSE;        /* input is waiting from the terminal, skip to EOP */
  234.   int command; /* current command */
  235.  
  236.   w = x = y = z = 0; /*Let's hope that each page specifies values for */
  237.              /*w,x,y,and z before it uses them.  Sincx Knuth */
  238.              /*says that DVI format should be readable from */
  239.              /*back to front, this seems reasonable.*/
  240.   do {
  241.     command = Nosignextend(dvifp, 1);
  242.     switch (command)  {
  243.     case SET1:case SET2:case SET3:case SET4:
  244.       {int val;
  245.        val = Nosignextend(dvifp, command-SET1+1);
  246.        if (!SkipMode) SetChar(val, command, xscreen, yscreen);}
  247.       break;
  248.     case SET_RULE:
  249.       {int val, val2;
  250.        val = Nosignextend(dvifp, 4);
  251.        val2 = Nosignextend(dvifp, 4);
  252.        if (!SkipMode) SetRule(val, val2, 1, xscreen, yscreen);}
  253.       break;
  254.     case PUT1:case PUT2:case PUT3:case PUT4:
  255.       {int val;
  256.        val = Nosignextend(dvifp,command-PUT1+1);
  257.        if (!SkipMode) SetChar(val, command, xscreen, yscreen);}
  258.       break;
  259.     case PUT_RULE:
  260.       {int val, val2;
  261.        val = Nosignextend(dvifp, 4);
  262.        val2 = Nosignextend(dvifp, 4);
  263.        if (!SkipMode) SetRule(val, val2, 0, xscreen, yscreen);}
  264.       break;
  265.     case NOP:
  266.       break;
  267.     case BOP:
  268.       (*cpagep) = ftell(dvifp) - 1;
  269.       {int i;
  270.        for (i=0; i<=9; i++)
  271.      Nosignextend(dvifp, 4);}
  272.       (*ppagep) = Nosignextend(dvifp, 4);
  273.       h = v = w = x = y = z = 0;
  274.       sp = 0;
  275.       fontptr = NULL;
  276.       if (PagesLeft) {
  277.     PagesLeft--;
  278.     if (PagesLeft <= 0) SkipMode = FALSE;
  279.       };
  280.       break;
  281.     case EOP:
  282.       if (borders && !SkipMode && !SkipEOP)
  283.     draw_borders(xscreen, yscreen);
  284.       if (SkipEOP) { SkipMode = FALSE; SkipEOP = FALSE; }
  285.       break;
  286.     case PUSH:
  287.       if (sp >= STACKSIZE)
  288.     fatal("stack overflow");
  289.       stack[sp].h = h;
  290.       stack[sp].v = v;
  291.       stack[sp].w = w;
  292.       stack[sp].x = x;
  293.       stack[sp].y = y;
  294.       stack[sp].z = z;
  295.       sp++;
  296.       break;
  297.     case POP:
  298.       --sp;
  299.       if (sp < 0)
  300.     fatal("stack underflow");
  301.       h = stack[sp].h;
  302.       v = stack[sp].v;
  303.       w = stack[sp].w;
  304.       x = stack[sp].x;
  305.       y = stack[sp].y;
  306.       z = stack[sp].z;
  307.       break;
  308.     case RIGHT1:case RIGHT2:case RIGHT3:case RIGHT4:
  309.       {int val;
  310.        val = signextend(dvifp,command-RIGHT1+1);
  311.        if (!SkipMode) MoveOver(val);}
  312.       break;
  313.     case W0:
  314.       if (!SkipMode) MoveOver(w);
  315.       break;
  316.     case W1:case W2:case W3:case W4:
  317.       w = signextend(dvifp,command-W1+1);
  318.       if (!SkipMode) MoveOver(w);
  319.       break;
  320.     case X0:
  321.       if (!SkipMode) MoveOver(x);
  322.       break;
  323.     case X1:case X2:case X3:case X4:
  324.       x = signextend(dvifp,command-X1+1);
  325.       if (!SkipMode) MoveOver(x);
  326.       break;
  327.     case DOWN1:case DOWN2:case DOWN3:case DOWN4:
  328.       {int val;
  329.        val = signextend(dvifp,command-DOWN1+1);
  330.        if (!SkipMode) MoveDown(val);}
  331.       break;
  332.     case Y0:
  333.       if (!SkipMode) MoveDown(y);
  334.       break;
  335.     case Y1:case Y2:case Y3:case Y4:
  336.       y = signextend(dvifp,command-Y1+1);
  337.       if (!SkipMode) MoveDown(y);
  338.       break;
  339.     case Z0:
  340.       if (!SkipMode) MoveDown(z);
  341.       break;
  342.     case Z1:case Z2:case Z3:case Z4:
  343.       z = signextend(dvifp,command-Z1+1);
  344.       if (!SkipMode) MoveDown(z);
  345.       break;
  346.     case FNT1:case FNT2:case FNT3:case FNT4:
  347.       if (!SkipMode) SetFntNum(Nosignextend(dvifp,command-FNT1+1));
  348.       break;
  349.     case XXX1:case XXX2:case XXX3:case XXX4:
  350.       {int k;
  351.        k = Nosignextend(dvifp,command-XXX1+1);
  352.        while (k--)
  353.      Nosignextend(dvifp, 1);}
  354.       break;
  355.     case FNT_DEF1:case FNT_DEF2:case FNT_DEF3:case FNT_DEF4:
  356.       if (preload) {
  357.     SkipFontDef (Nosignextend(dvifp, command-FNT_DEF1+1), dvifp);
  358.       } else {
  359.     ReadFontDef (Nosignextend(dvifp, command-FNT_DEF1+1), dvifp);
  360.       }
  361.       break;
  362.     case PRE:
  363.       fatal("PRE occurs within file");
  364.       break;
  365.     case POST:
  366.       fseek(dvifp, (*cpagep), 0);
  367.       SkipMode = FALSE;
  368.       PagesLeft = 0;
  369.       break;
  370.     case POST_POST:
  371.       fatal("POST_POST with no preceding POST");
  372.       break;
  373.     default:
  374.       if (command >= FONT_00 && command <= FONT_63)
  375.      {if (!SkipMode) SetFntNum(command - FONT_00);}
  376.       else if (command >= SETC_000 && command <= SETC_127)
  377.     {if (!SkipMode) SetChar(command - SETC_000, command, xscreen, yscreen);}
  378.       else
  379.     fatal("%d is an undefined command", command);
  380.       break;
  381.     }                /* case */
  382.   } while (command != EOP || SkipMode);
  383. }
  384.  
  385. /* compute the actual size factor given the approximation */
  386. float ActualFactor(unmodsize)
  387. int unmodsize;  /* actually factor * 1000 */
  388. {
  389.   float realsize;        /* the actual magnification factor */
  390.  
  391.   realsize = (float)unmodsize / 1000.0;
  392.   /* a real hack to correct for rounding in some cases--rkf */
  393.   if(unmodsize==1095) realsize = 1.095445; /*stephalf*/
  394.   else if(unmodsize==1315) realsize=1.314534; /*stepihalf*/
  395.   else if(unmodsize==2074) realsize=2.0736; /*stepiv*/
  396.   else if(unmodsize==2488) realsize=2.48832; /*stepv*/
  397.   else if(unmodsize==2986) realsize=2.985984; /*stepiv*/
  398.   /* the remaining magnification steps are represented with sufficient
  399.      accuracy already */
  400.   return(realsize);
  401. }
  402.  
  403. int DoConv(num, den, convResolution)
  404. {
  405.     register float conv;
  406.     conv = ((float)num/(float)den) * 
  407. #ifdef USEGLOBALMAG
  408.       ActualFactor(mag) *          /* put back in by clp, 8/22/84 */
  409. /*    ((float) mag/1000.0) *           and this taken out...         */
  410. #endif
  411.     ((float)convResolution/254000.0);
  412.     return((int) (1.0 / conv + 0.5));
  413. }
  414.  
  415. void fatal(fmt, args)/* issue a fatal error message */
  416.      char *fmt;    /* format */
  417.      char *args; /* arguments */
  418. {
  419.     fprintf(stderr, "Fatal error.  ");
  420.     _doprnt(fmt, &args, stderr);
  421.     fprintf(stderr, "\n");
  422.     exit(1);
  423. }
  424.  
  425. void FindPostAmblePtr(postambleptr, dvifp)
  426.      long *postambleptr;
  427.      FILE *dvifp;
  428. /* this routine will move to the end of the file and find the start
  429.     of the postamble */
  430. {
  431.     int     i;
  432.  
  433.     fseek (dvifp, (long) 0, 2);   /* goto end of file */
  434.     *postambleptr = ftell (dvifp) - 4;
  435.     fseek (dvifp, *postambleptr, 0);
  436.  
  437.     while (TRUE) {
  438.     fseek (dvifp, --(*postambleptr), 0);
  439.     if (((i = Nosignextend(dvifp, 1)) != 223) &&
  440.         (i != DVIFORMAT))
  441.         fatal ("Bad end of DVI file");
  442.     if (i == DVIFORMAT)
  443.         break;
  444.     }
  445.     fseek (dvifp, (*postambleptr) - 4, 0);
  446.     *postambleptr = Nosignextend(dvifp, 4);
  447.     fseek (dvifp, *postambleptr, 0);
  448. }
  449.  
  450. void GetBytes(fp, cp, n)    /* get n bytes from file fp */
  451.      register FILE *fp;    /* file pointer     */
  452.      register char *cp;    /* character pointer */
  453.      register int n; /* number of bytes  */
  454. {
  455.     while (n--)
  456.     *cp++ = getc(fp);
  457. }
  458.  
  459. void getfontdef(dvifp)
  460.      FILE *dvifp;
  461. /* Read the font  definitions as they  are in the  postamble of the  DVI
  462.    file.  Note that the font directory  is not yet loaded.  In order  to
  463.    adapt ourselves to the existing "verser" the following font paramters
  464.    are  copied     onto  output    fontno  (4   bytes),  chksum,    fontmag,
  465.    fontnamelength (1 byte), fontname.  At the end, a -1 is put onto  the
  466.    file.*/
  467. {
  468.     char    str[50], *calloc ();
  469.     unsigned char   byte;
  470.     int     i, fnamelen;
  471.  
  472.     while (((byte = Nosignextend(dvifp, 1)) >= FNT_DEF1) &&
  473.     (byte <= FNT_DEF4)) {
  474.     switch (byte) {
  475.     case FNT_DEF1:
  476.         ReadFontDef (Nosignextend(dvifp, 1), dvifp);
  477.         break;
  478.     case FNT_DEF2:
  479.         ReadFontDef (Nosignextend(dvifp, 2), dvifp);
  480.         break;
  481.     case FNT_DEF3:
  482.         ReadFontDef (Nosignextend(dvifp, 3), dvifp);
  483.         break;
  484.     case FNT_DEF4:
  485.         ReadFontDef (Nosignextend(dvifp, 4), dvifp);
  486.         break;
  487.     default:
  488.         fatal ("Bad byte value in font defs");
  489.         break;
  490.     }
  491.     }
  492.     if (byte != POST_POST)
  493.     fatal ("POST_POST missing after fontdefs");
  494. }
  495.  
  496. void MoveDown(a)
  497. int a;
  498. {
  499.   v += a;
  500. }
  501.  
  502. void MoveOver(b)
  503. int b;
  504. {
  505.     h += b;
  506. }
  507.  
  508. void OpenFontFile()
  509. /* The original version of this dvi driver reopened the font file  each
  510.    time the font changed, resulting in an enormous number of relatively
  511.    expensive file  openings.   This version  keeps  a cache  of  up  to
  512.    MAXOPEN open files,  so that when  a font change  is made, the  file
  513.    pointer, pxlfp, can  usually be  updated from the  cache.  When  the
  514.    file is not found in  the cache, it must  be opened.  In this  case,
  515.    the next empty slot  in the cache  is assigned, or  if the cache  is
  516.    full, the least used font file is closed and its slot reassigned for
  517.    the new file.  Identification of the least used file is based on the
  518.    counts of the number  of times each file  has been "opened" by  this
  519.    routine.  On return, the file pointer is always repositioned to  the
  520.    beginning of the file.*/
  521. {
  522.     register int i,least_used,current;
  523.  
  524. #ifdef DEBUG
  525.     if (Debug) printf("Open Font file\n");
  526. #endif
  527.     if (pfontptr == fontptr)
  528.         return;                 /* we need not have been called */
  529.  
  530.     for (current = 1;
  531.     (current <= nopen) &&
  532.         (pixel_files[current].pixel_file_id != fontptr->font_file_id);
  533.     ++current); /* try to find file in open list */
  534.     if (current <= nopen) {      /* file already open */
  535.     pxlfp = pixel_files[current].pixel_file_id;
  536.     fseek(pxlfp,0,0);    /* reposition to start of file */
  537.     } else {                        /* file not in open list */
  538.         if (nopen < MAXOPEN)    /* just add it to list */
  539.             current = ++nopen;
  540.     else {/* list full -- find least used file, close it, and */
  541.           /* reuse slot for new file */ 
  542.         least_used = 1;
  543.             for (i = 2; i <= MAXOPEN; ++i)
  544.             if (pixel_files[least_used].use_count >
  545.                     pixel_files[i].use_count)
  546.             least_used = i;
  547.         fclose(pixel_files[least_used].pixel_file_id);
  548.         pixel_files[least_used].fptr -> font_file_id = 0;
  549.         current = least_used;
  550.         }
  551.         if ((pxlfp=fopen(fontptr->name,"r")) == NULL) {
  552.       perror ("");
  553.       fatal("PXL file \"%s\" could not be opened; %d PXL files are open",
  554.         fontptr->name,nopen);
  555.     };
  556.     pixel_files[current].pixel_file_id = pxlfp;
  557.     pixel_files[current].fptr = fontptr;
  558.     pixel_files[current].use_count = 0;
  559.     }
  560.     pfontptr = fontptr;            /* make previous = current font */
  561.     fontptr->font_file_id = pxlfp;    /* set file identifier */
  562.     pixel_files[current].use_count++;    /* update reference count */
  563. }
  564.  
  565. int PixRound(x, conv)    /* return rounded number of pixels */
  566.      register int x;        /* in DVI units     */
  567.      int conv;        /* conversion factor */
  568. {
  569.   return((int)((x + (conv >> 1)) / conv));
  570. }
  571.  
  572. /* Put the given font pointer on the global list of font pointers and */
  573.  /* make it the current font. */
  574. void installfontptr (tfontptr)
  575.      struct font_entry *tfontptr;
  576. {
  577.   tfontptr->next = hfontptr;
  578.   fontptr = hfontptr = tfontptr;
  579. }
  580.  
  581. int ReadFontDef(k, dvifp)
  582.      int k;
  583.      FILE *dvifp;
  584. {
  585.   int t, i;
  586.   register struct font_entry *tfontptr;    /* temporary font_entry pointer   */
  587.   register struct char_entry *tcharptr;    /* temporary char_entry pointer  */
  588.   char *direct, *tcp, *tcp1;
  589.   int found;
  590.   char curarea[STRSIZE];
  591.  
  592.   if ((tfontptr = NEW(struct font_entry)) == NULL)
  593.     fatal("can't malloc space for font_entry");
  594.  
  595.   tfontptr->k = k;
  596.   tfontptr->c = Nosignextend(dvifp, 4);    /* checksum */
  597.   tfontptr->s = Nosignextend(dvifp, 4);    /* space size */
  598.   tfontptr->d = Nosignextend(dvifp, 4);    /* design size */
  599.   tfontptr->a = Nosignextend(dvifp, 1);    /* area length for font name */
  600.   tfontptr->l = Nosignextend(dvifp, 1);    /* device length */
  601.   GetBytes(dvifp, tfontptr->n, tfontptr->a+tfontptr->l);
  602.   tfontptr->n[tfontptr->a+tfontptr->l] = '\0';
  603.   tfontptr->font_space = tfontptr->s/6;    /* never used */
  604.   tfontptr->font_mag = (int)((ActualFactor((int)(((float)tfontptr->s/
  605.                           (float)tfontptr->d)*1000.0 + 0.5)) * 
  606. #ifdef USEGLOBALMAG
  607.                   ActualFactor(mag) *
  608. #endif
  609.                   (float)RESOLUTION * 5.0) + 0.5);
  610.  
  611. #ifdef DEBUG
  612.   printf ("Trying to open font %s, mag %d.\n", tfontptr -> n, 
  613.       tfontptr -> font_mag);
  614. #endif
  615.   /* Look for a font with the same file name as tfontptr in */
  616.   /* closedfonts. */
  617.   {
  618.     struct font_entry *prevptr=NULL; /* Follows curptr in the closed */
  619.     /* fonts list. */
  620.     struct font_entry *curptr;
  621.     for (curptr = closedfonts;
  622.      (curptr != NULL) &&
  623.      !((curptr->font_mag == tfontptr -> font_mag) &&
  624.        (strcmp (curptr -> n, tfontptr -> n) == 0));
  625.      prevptr = curptr,curptr = curptr -> next);
  626.     if (curptr != NULL) {
  627. #ifdef DEBUG
  628.       printf ("Re-opening closed font %s, mag %d, filename is %s.\n",
  629.           tfontptr -> n, tfontptr -> font_mag, curptr -> name);
  630. #endif
  631.       /* We found a font with the same name in the list of closed */
  632.       /* fonts.  Now delete it from the list of closed fonts. */
  633.       if (prevptr == NULL) {
  634.     /* curptr was the first font on the list of closed fonts. */
  635.     closedfonts = closedfonts -> next;
  636.       } else {
  637.     /* curptr wasn't first. */
  638.     prevptr -> next = curptr -> next;
  639.       };
  640.       /* Verify that all of the relevant font parameters are the */
  641.       /* same. */
  642.       if ((tfontptr -> c != curptr -> c) ||
  643.       (tfontptr -> s != curptr -> s) ||
  644.       (tfontptr -> d != curptr -> d)) {
  645.       fatal ("Font %s at magnification %d reencountered with different parameters.",
  646.          tfontptr -> n, tfontptr -> font_mag);
  647.     };
  648.       curptr -> k = tfontptr -> k;
  649.       /* The following is somewhat bogus.  I should fix the above */
  650.       /* code so that no mallocs happen if the font is in the closed */
  651.       /* list.  Oh well, spaghetti code begats spaghetti code. */
  652.       free (tfontptr);
  653.       installfontptr (curptr);
  654.     } else {
  655.       /* Opening a new font. */
  656.       if (tfontptr->a != 0) {
  657.     sprintf(tfontptr->name, "%s.%dpxl", tfontptr->n, tfontptr->font_mag);
  658.       } else {
  659.     direct = PXLpath;
  660.     found = FALSE;
  661.     do { 
  662.       tcp = index(direct, ':');
  663.       if (tcp == NULL) tcp = strlen(direct) + direct;
  664.       strncpy(curarea, direct, tcp-direct);
  665.       tcp1 = curarea + (tcp - direct);
  666.       *tcp1++ = '/';
  667.       *tcp1++ = '\0';
  668.  
  669.       sprintf(tfontptr->name, "%s%s.%dpxl", curarea, tfontptr->n, tfontptr->font_mag);
  670.       found = (access(tfontptr->name, READ) == 0);
  671.       if (*tcp) direct = tcp + 1; else direct = tcp;
  672.     } while ( !found && *direct != '\0');
  673.       };
  674. #ifdef DEBUG
  675.       printf ("Filename is %s.\n", tfontptr -> name);
  676. #endif
  677.       installfontptr (tfontptr);
  678.       OpenFontFile();
  679.       if ((t = Nosignextend(pxlfp, 4)) != PXLID)
  680.     fatal("PXL ID = %d, can only process PXL ID = %d files",
  681.           t, PXLID);
  682.       fseek(pxlfp, -20, 2);
  683.       t = Nosignextend(pxlfp, 4);
  684.       if ((tfontptr->c != 0) && (t != 0) && (tfontptr->c != t))
  685.     fatal("font = \"%s\",\n-->font checksum = %d,\n-->dvi checksum = %d",
  686.           tfontptr->name, tfontptr->c, t);
  687.       tfontptr->magnification = Nosignextend(pxlfp, 4);
  688.       tfontptr->designsize = Nosignextend(pxlfp, 4);
  689.  
  690.       fseek(pxlfp, Nosignextend(pxlfp, 4) * 4, 0);
  691.  
  692.       for (i = FIRSTPXLCHAR; i <= LASTPXLCHAR; i++) {
  693.     tcharptr = &(tfontptr->ch[i]);
  694.     tcharptr->width = Nosignextend(pxlfp, 2);
  695.     tcharptr->height = Nosignextend(pxlfp, 2);
  696.     tcharptr->xOffset= signextend(pxlfp, 2);
  697.     tcharptr->yOffset = signextend(pxlfp, 2);
  698.     tcharptr->where.isloaded = FALSE;
  699.     tcharptr->where.address.fileOffset = Nosignextend(pxlfp, 4) * 4;
  700.     tcharptr->tfmw = ((float)Nosignextend(pxlfp, 4)*(float)tfontptr->s) /
  701.       (float)(1<<20);
  702.       }
  703.     }
  704.   }
  705. }
  706.  
  707. int readpostamble (dvifp)
  708.      FILE *dvifp;
  709. /* This  routine  is  used  to  read  in  the  postamble  values.    It
  710.    initializes the magnification and checks  the stack height prior  to
  711.    starting printing the document.  It returns the number of pages in the document. */
  712. {
  713.     FindPostAmblePtr (&postambleptr, dvifp);
  714.     if (Nosignextend(dvifp, 1) != POST)
  715.     fatal ("POST missing at head of postamble");
  716. #ifdef DEBUG
  717.     if (Debug) fprintf (stderr, "got POST command\n");
  718. #endif
  719.     /*      lastpageptr = */ Nosignextend(dvifp, 4);
  720.     num = Nosignextend(dvifp, 4);
  721.     den = Nosignextend(dvifp, 4);
  722.     mag = Nosignextend(dvifp, 4);
  723.     hconv = DoConv(num, den, hconvRESOLUTION);
  724.     vconv = DoConv(num, den, vconvRESOLUTION);
  725.  
  726.     Nosignextend(dvifp, 4);    /* height-plus-depth of tallest page */
  727.     Nosignextend(dvifp, 4);    /* width of widest page */
  728.     if (Nosignextend(dvifp, 2) >= STACKSIZE)
  729.     fatal ("Stack size is too small");
  730.     return (Nosignextend(dvifp, 2));    /* this reads the number of pages in */
  731.     /* the DVI file */
  732. }
  733.  
  734. void LoadAChar(ptr)
  735.      register struct char_entry *ptr;
  736. {
  737.   if (ptr->where.address.fileOffset == 0) {
  738.     ptr->where.address.pixrectptr = NULL;
  739.     return;
  740.   }
  741.   OpenFontFile();
  742.   fseek(pxlfp, ptr->where.address.fileOffset, 0);
  743.   ptr->where.address.pixrectptr =
  744.     read_char (pxlfp, ptr -> width, ptr -> height);
  745.   ptr->where.isloaded = TRUE;
  746. }
  747.  
  748. /* Display a character.*/
  749. void SetChar(c, command, xscreen, yscreen)
  750.      int c; /* Character to display */
  751.      int command; /* Command we are doing */
  752.      int xscreen, yscreen;
  753. {
  754.   register struct char_entry *ptr; /* temporary char_entry pointer */
  755.   int k;
  756.   int hh; /* current horizontal position in pixels */
  757.   int vv; /* current vertical position in pixels */
  758.  
  759.   ptr = &(fontptr->ch[c]);
  760.   hh = PixRound(h, hconv);
  761.   vv = PixRound(v, vconv);
  762.   if (!ptr->where.isloaded) LoadAChar(ptr);
  763.   show_char (hh-ptr->xOffset-xscreen, vv-ptr->yOffset-yscreen,
  764.          ptr->width, ptr->height,
  765.          ptr->where.address.pixrectptr);
  766.   if (command <= SET4) h += ptr->tfmw;
  767. }
  768.  
  769. void SetFntNum(k)
  770.      int k;
  771. /*  this routine is used to specify the font to be used in printing future
  772.     characters */
  773. {
  774.     fontptr = hfontptr;
  775.     while ((fontptr!=NULL) && (fontptr->k!=k))
  776.     fontptr = fontptr->next;
  777.     if (fontptr == NULL)
  778.     fatal("font %d undefined", k);
  779. }
  780.  
  781. void SetRule(a, b, Set, xscreen, yscreen)
  782.      int a, b;
  783.      BOOLEAN Set;
  784.      int xscreen, yscreen;
  785. {        /*     this routine will draw a rule on the screen */
  786.     int ehh, evv;
  787.     int hh; /* current horizontal position in pixels */
  788.   int vv; /* current vertical position in pixels */
  789.  
  790.     hh = PixRound(h, hconv);
  791.     vv = PixRound(v-a, vconv);
  792.     ehh = PixRound(h + b, hconv);
  793.     evv = PixRound(v, vconv);
  794.     if (hh == ehh) ehh++;
  795.     if (vv == evv) vv--;
  796.     if ((a > 0) && (b > 0))
  797.       black_box (hh-xscreen, vv-yscreen, ehh-hh, evv-vv);
  798.     if (Set) {
  799.     h += b;
  800. /*        v += a; */
  801.     }
  802. }
  803.  
  804. void SkipFontDef(k, dvifp)
  805.      int k;
  806.      FILE *dvifp;
  807. {
  808.   int a, l;
  809.   char n[STRSIZE];
  810.  
  811.   Nosignextend(dvifp, 4);
  812.   Nosignextend(dvifp, 4);
  813.   Nosignextend(dvifp, 4);
  814.   a = Nosignextend(dvifp, 1);
  815.   l = Nosignextend(dvifp, 1);
  816.   GetBytes(dvifp, n, a+l);
  817. }
  818.  
  819.